解决Quark模组无法加载赞助者信息无限报错的问题 您所在的位置:网站首页 error loading翻译 解决Quark模组无法加载赞助者信息无限报错的问题

解决Quark模组无法加载赞助者信息无限报错的问题

2023-10-01 17:13| 来源: 网络整理| 查看: 265

在使用夸克MOD时,经常会在后台看到这样的报错:“Failed to load patreon information”。

根据详细报错栈和见名知义的命名以及开源代码,可以定位到是夸克MOD尝试加载赞助者信息时因为国内无法访问"https://raw.githubusercontent.com/Vazkii/Quark/master/contributors.properties"导致的。

实际上这不是BUG,曾经多次有人向作者提出issue,但是作者都在无回复且没有任何ref的情况下直接关闭并且拒绝提供关闭打印此报错的开关。

https://github.com/VazkiiMods/Quark/issues/3160

https://github.com/VazkiiMods/Quark/issues/3331

https://github.com/VazkiiMods/Quark/issues/3416

在使用了一些工具自动监测服务器异常栈的时候,这个错误导致服务器没完没了的误警报,严重干扰运维。

解决方法1:修改hosts

raw.githubusercontent.com的IP地址是

185.199.108.133

185.199.109.133

185.199.110.133

185.199.111.133

但是可以肯定的是,如果hosts能解决问题你就不会来看我的专栏了。

分析代码

从git下载代码,找到vazkii.quark.base.handler.ContributorRewardHandler。可以根据报错栈定位到,实际发生错误的,产生网络请求的代码位于vazkii.quark.base.handler.ContributorRewardHandler.ThreadContributorListLoader中。

罪魁祸首就是"Quark.LOG.error("Failed to load patreon information", e);"这句代码导致每次同步失败都会产生错误栈打印。

修改代码建议使用Idea(https://www.jetbrains.com/idea/);

删除指的是将代码注释掉(Java语言是//);

解决方法2:提供Http-Proxy助其能访问

此方法是最符合人类行为道德的解决办法,再请求的代码中添加代理功能并搭建代理即可,注意将InetSocketAddress修改为你实际的http-proxy地址。

之后使用build构建mod。

解决方法3:删除日志打印语句

不是所有人所有服务器都有能力在宿主搭建代理(比如MC主机出租,只能选择启动/关闭/重启,不能随意运行其他软件),所以这里提供一种不再打印错误日志的修复办法。

在vazkii.quark.base.handler.ContributorRewardHandler.ThreadContributorListLoader#run方法中,删除掉Quark.LOG.error("Failed to load patreon information", e);即可屏蔽掉日志输出,就算实际执行的代码闹翻天,控制台也会无事发生。

之后使用build构建mod。

解决方法4:关闭检查功能

作为程序员和运维,其实是不能容忍跑不通没有意义的代码在后台不停的报错的。所以这里提供另一种严重违反道德的做法,即禁用赞助者信息更新。

这个方法可能会在MOD更新后失效,毕竟代码随时可能会变。

初始化赞助者更新的方法为vazkii.quark.base.handler.ContributorRewardHandler#init(实际上把init方法体内的所有东西删除就可以了,但是作为程序员的极度强迫症,一定要清理干净所有调用才舒服。)

此方法有两个引用:

1:玩家加入服务器时

vazkii.quark.base.handler.ContributorRewardHandler#onPlayerJoin

注释掉注解@SubscribeEvent和@OnlyIn(Dist.DEDICATED_SERVER)或者直接把这个方法给扬了,即可不再向Forge注册玩家加入的事件。

2:MOD启动时vazkii.quark.base.proxy.CommonProxy#setup将最后initContributorRewards的调用注释掉

3:MOD在客户端启动时vazkii.quark.base.proxy.ClientProxy#initContributorRewards将最后super.initContributorRewards的调用注释掉

之后使用build构建mod。

解决方法4:直接编辑字节码删除打印日志的语句

由于网络问题在国内编译MOD会耗费巨大的时间而且99%的情况下会因为网络问题失败。导致方法2,3都不可用(比如我使用500M的国际CN2线路都需要10~20分钟才能同步下来各种依赖和库,如果直接使用直连网络,下载100M的gradle就需要1个小时了)。

直接删除打印报错日志的那句代码是更快捷的方法,基于字节码修改工具虽然可以反编译修改原始代码,但是二次从代码编译为新的字节码是需要依赖库的,所以只能直接修改字节码,因为字节码过于复杂过于底层,所以添加内容是极度困难的,故采用删除日志打印语句的解决方法三。

这里使用了Recaf这个工具。MOD文件使用Quark-r2.4-319.jar之后的版本肯定会有各种更新,所以需要自行判断删除哪些代码,如何修改GOTO语句到哪个位置(要不怎么会把这个“简单”的方法排在后边)。

1:使用Recaf打开下载的jar文件,定位到类;

2:右键tab更改为表格视图,右键代码进入ASM编辑模式;

打开ASM编辑

3:找到打印日志的那句话

找到调用Logger打印的语句

4:修改字节码

修改字节码

删除掉Y:对应位置原来的代码,从"GETSTATIC" 到 "INVOKEINTERFACE",修改为GOTO Z,保存,导出jar。

含义是(简单理解):Z对应的代码为RETURN 即方法的"}",本来的代码执行Z之前会执行Y,即打印日志(调用Logger.error),将Y直接修改为GOTO即相当于删除本句代码并且不会导致代码行号重排,避免了大幅度修改字节码引起的各种问题(大规模增加代码比如使用解决方法二,将会涉及修改常量池、引入新的类、类索引、修改异常表、修复由于修改导致的序号重排等纯手动高难度操作,手动修改几乎必出错)。

彩蛋:实际上这样修改的代码再次编译后会变成这样:

如果只看反编译的代码是很正常的,去掉了打印的代码,使其变成ignore。

二次编译后反编译

实际上字节码会变成这个比较鬼畜的样子(X从GOTO Z变成GOTO Y,Y从GOTO Z变成RETURN,Z直接空了)。

二次编译后的字节码



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有